package com.itheima.reggie.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.itheima.reggie.common.BaseContext;
import com.itheima.reggie.common.R;

import com.itheima.reggie.entity.*;

import com.itheima.reggie.service.*;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;


import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单
 */
@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private OrderService orderService;
    @Autowired
    private ShoppingCartService shoppingCartService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private DishService dishService;
    @Autowired
    private SetmealService setmealService;
    /**
     * 用户下单
     *
     * @param orders
     * @return
     */
    @PostMapping("/submit")
    public R<String> submit(@RequestBody Orders orders) {
        log.info("前端传回的订单数据:{}", orders);
//        添加下单数据
        orderService.submit(orders);
        return R.success("下单成功");
    }

    /**
     * 分页升序查询订单
     *
     * @param page
     * @param pageSize
     * @return
     */
    @GetMapping("/userPage")
    public R<Page<OrderDto>> queryOrder(Integer page, Integer pageSize) {
//        日志
        log.info("分页查询，当前页：{}，页大小：{}", page, pageSize);
//        创建分页构造器
        Page<Orders> ordersPage = new Page<>(page, pageSize);
        Page<OrderDto> orderDtoPage = new Page<>();
//        获取当前用户id
        Long currentId = BaseContext.getCurrentIdUser();
//        条件构造器
        LambdaQueryWrapper<Orders> condition = new LambdaQueryWrapper<>();
        condition.eq(Orders::getUserId, currentId).orderByDesc(Orders::getOrderTime);
        orderService.page(ordersPage, condition);
//        将从前端传来的数据在order中查到的信息复制到dto中
        BeanUtils.copyProperties(ordersPage, orderDtoPage);
//        将order中的records记录封装到到dto
        List<OrderDto> orderDtoList = ordersPage.getRecords().stream().map((item) -> {
//      创建dto对象
            OrderDto orderDto = new OrderDto();
//      将order中实体复制到dto中，因为要返回的是dto封装的数据
            BeanUtils.copyProperties(item, orderDto);
//      获取订单id，然后根据id去订单细节中查询定了哪些菜品和套餐，
            Long orderId = item.getId();
//      条件构造器
            LambdaQueryWrapper<OrderDetail> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(OrderDetail::getOrderId, orderId);
//      查询，只需要菜品和套餐信息
            List<OrderDetail> orderDetailList = orderDetailService.list(queryWrapper);
//            往dto中注入订单细则信息
            orderDto.setOrderDetails(orderDetailList);
            return orderDto;
//            返回dto
        }).collect(Collectors.toList());
//                设置dto的records
        orderDtoPage.setRecords(orderDtoList);
//        返回结果
        return R.success(orderDtoPage);
    }

    /**
     * 查看订单
     *
     * @param page
     * @param pageSize
     * @param number
     * @param beginTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    @GetMapping("/page")
//  前端传回的数据有当前页，查询条数，订单编号，开始时间，结束时间
    public R<Page> query(Integer page, Integer pageSize, Long number,
                         String beginTime, String endTime) throws ParseException {
//        日志
        log.info("分页查询，当前页：{}，页大小：{},订单编号：{}，" +
                        "开始时间：{}，结束时间：{}",
                page, pageSize, number, beginTime, endTime);
//        处理时间
        SimpleDateFormat simpleDateFormat =
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        创建分页构造器
        Page<Orders> ordersPage = new Page<>(page, pageSize);
//        条件构造器
        LambdaQueryWrapper<Orders> lwq = new LambdaQueryWrapper<>();
//      排序
        lwq.orderByDesc(Orders::getOrderTime);
//        拼接订单编号条件
        lwq.eq(null != number, Orders::getNumber, number);
//        对前端传来的起始时间和结束时间进行非空判断
        if (null != beginTime && null != endTime) {
            //        设置起始时间
            Date begin = simpleDateFormat.parse(beginTime);
            //        设置结束时间
            Date end = simpleDateFormat.parse(endTime);
//        拼接条件，起始时间要小于结束时间
            lwq.between(end.compareTo(begin) > 0,
                    Orders::getOrderTime, beginTime, endTime);
        }

//        查询
        orderService.page(ordersPage, lwq);
//        返回结果
        return R.success(ordersPage);
    }

    /**
     * 更改派送状态
     *
     * @param orders
     * @return
     */
    @PutMapping
    public R<String> update(@RequestBody Orders orders) {
//        日志
        log.info("前端传回的数据：{}", orders);
//        条件构造器
        LambdaUpdateWrapper<Orders> updateWrapper = new LambdaUpdateWrapper<>();
//        拼接条件
        updateWrapper.eq(null != orders.getId(), Orders::getId, orders.getId())
                .set(Orders::getStatus, orders.getStatus());
//        更新操作
        orderService.update(updateWrapper);
        return R.success("状态更新成功");
    }
    /**
     * 文件下载（失败了会返回一个有部分数据的Excel）
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link Orders}
     * <p>
     * 2. 设置返回的 参数
     * <p>
     * 3. 直接写，这里注意，finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
     */
    @GetMapping("/export")
    public void download(HttpServletResponse response) throws IOException {
//        将订单中的数据以集合的方式给到Excel中
        List<Orders> list = orderService.list();

        //List<Orders> list = ordersService.list();
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), Orders.class).registerConverter(new LongStringConverter()).sheet("模板").doWrite(list);
    }
    @PostMapping("/again")
    public R<String> again(@RequestBody Orders orders){

////    日志
        log.info("前端传回的数据：{}",orders.toString());
////    获取当前用户
        Long currentIdUser = BaseContext.getCurrentIdUser();
////    获取前端传回来的订单id
        Long ordersId = orders.getId();
////    订单条件构造器
        LambdaQueryWrapper<Orders> ordersLambdaQueryWrapper = new LambdaQueryWrapper<>();
////    获取该订单对象
        ordersLambdaQueryWrapper.eq(null != ordersId,Orders::getId,ordersId);
        Orders orders1 = orderService.getOne(ordersLambdaQueryWrapper);
////    获取该订单编号,该订单编号是是订单细节里的order_id
        String orders1Number = orders1.getNumber();
////    订单明细条件构造器
        LambdaQueryWrapper<OrderDetail> orderDetailLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderDetailLambdaQueryWrapper.eq(orders1Number != null,OrderDetail::getOrderId,orders1Number);
////    获取该订单明细里的所有与该订单有关的数据
        List<OrderDetail> orderDetails = orderDetailService.list(orderDetailLambdaQueryWrapper);
////    创建购物车集合，后续菜品和套餐都会添加到集合中
        List<ShoppingCart> shoppingCarts = new ArrayList<>();
////    购物车条件构造器
        LambdaQueryWrapper<ShoppingCart> shoppingCartLambdaQueryWrapper = new LambdaQueryWrapper<>();
        shoppingCartLambdaQueryWrapper.eq(null != currentIdUser,ShoppingCart::getUserId,currentIdUser);
////    清空原来的购物车
        shoppingCartService.remove(shoppingCartLambdaQueryWrapper);
////    遍历订单明细
        for (OrderDetail orderDetail : orderDetails) {
            ////    创建购物车对象
            ShoppingCart shoppingCart = new ShoppingCart();
////    设置购物车对象中的数据
         shoppingCart.setUserId(currentIdUser);
         shoppingCart.setNumber(orderDetail.getNumber());
         shoppingCart.setAmount(orderDetail.getAmount());
         shoppingCart.setCreateTime(LocalDateTime.now());
////    判断菜品是否为空
            if (orderDetail.getDishId() != null){
                ////    不为空,查出该菜品
                LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(Dish::getId,orderDetail.getDishId());
                Dish dish = dishService.getOne(lambdaQueryWrapper);
                shoppingCart.setDishId(dish.getId());
                shoppingCart.setName(dish.getName());
                shoppingCart.setImage(dish.getImage());
                shoppingCart.setDishFlavor(orderDetail.getDishFlavor());
                shoppingCarts.add(shoppingCart);
            }else if(orderDetail.getSetmealId() != null){////    判断套餐是否为空,
                ///    不为空,根据套餐id查询对应菜品数据
                LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();
                setmealLambdaQueryWrapper.eq(Setmeal::getId,orderDetail.getSetmealId());
                Setmeal setmeal = setmealService.getOne(setmealLambdaQueryWrapper);
                shoppingCart.setSetmealId(setmeal.getId());
                shoppingCart.setName(setmeal.getName());
                shoppingCart.setImage(setmeal.getImage());
                shoppingCarts.add(shoppingCart);
            }
        }

////    执行购物车添加操作
        shoppingCartService.saveBatch(shoppingCarts);
////    返回结果
        return R.success("下单成功");
    }


}
